﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ControlAccessUser.Presenter;
using ControlAccessUser.Model;

namespace ControlAccessUser.Tests
{
    [TestClass]
    public class PrincipalTest
    {
        MockPrincipalView vPrincipalView;
        PresenterPrincipal pPrincipal;

        [TestInitialize]
        public void initial()
        {
            vPrincipalView = new MockPrincipalView();
            pPrincipal = new PresenterPrincipal(vPrincipalView);

            ControlAccessUser.DataAccess.ControlAccessUserEntities.Instance.Users.Add(new User() { UserName = "gary", UserPassword = "123456" });
            ControlAccessUser.DataAccess.ControlAccessUserEntities.Instance.SaveChanges();
        }

        [TestCleanup]
        public void clean()
        {
            ControlAccessUser.DataAccess.ControlAccessUserEntities.Instance.LimpiarDB();
        }

        /// <summary>
        /// Verifica que el logout se hizo correctamente
        /// </summary>
        [TestMethod]
        public void SuccessfulLogout()
        {
            CheckLogin("gary", "123456");//Para registrar el login en la BD
            vPrincipalView.UserLogin = SearchUserByUserNameAndUserPassword(new User() {UserName="gary",UserPassword="123456" }).First();
            vPrincipalView.EnterDataLogoutSuccessful();
            pPrincipal.Logout();//Para actualizar el login en la BD(Logout)
            ICollection<Login> Logins = (from Login in ControlAccessUser.DataAccess.ControlAccessUserEntities.Instance.Logins
                                         where Login.UserId == vPrincipalView.UserLogin.UserId && Login.LoginId == (from Log in ControlAccessUser.DataAccess.ControlAccessUserEntities.Instance.Logins
                                                                                                                    select Log.LoginId).Max()
                                        select Login).ToList();
            Assert.AreNotEqual(null, Logins.First().DataTimeLogoutUser);
        }

        /// <summary>
        /// Verifica que logout se canceló
        /// </summary>
        [TestMethod]
        public void CancelLogout()
        {
            CheckLogin("gary", "123456");
            vPrincipalView.UserLogin = SearchUserByUserNameAndUserPassword(new User() { UserName = "gary", UserPassword = "123456" }).First();
            vPrincipalView.EnterDataLogoutCanceled();
            pPrincipal.Logout();
            ICollection<Login> Logins = DataAccess.DataAccessLogin.SearchLastRegisterLogin(vPrincipalView.UserLogin);
            Assert.AreEqual(null, Logins.First().DataTimeLogoutUser);
        }

        private ICollection <User> SearchUserByUserNameAndUserPassword(User UserToVerify)
        {
            return (from user in ControlAccessUser.DataAccess.ControlAccessUserEntities.Instance.Users
             where
             user.UserName == UserToVerify.UserName &&
             user.UserPassword == UserToVerify.UserPassword
             select user).ToList();
        }

        private void CheckLogin(string UserName, string UserPassword)
        {
            User UserToVerify = new User() { UserName = UserName, UserPassword = UserPassword };
            vPrincipalView.UserLogin = SearchUserByUserNameAndUserPassword(UserToVerify).First(); ;
            RegisterLoginUser(new Login() { DataTimeLoginUser = DateTime.Now, DataTimeLogoutUser = null, User = vPrincipalView.UserLogin});
        }

        private void RegisterLoginUser(Login Login)
        {
            ICollection<Login> Log = DataAccess.DataAccessLogin.SearchLastRegisterLogin(Login.User);
            if (Log.Count == 0)
            {
                DataAccess.DataAccessLogin.InsertNewLogin(Login);
            }
            else
            {
                if (Log.First().DataTimeLogoutUser != null)
                {
                    DataAccess.DataAccessLogin.InsertNewLogin(Login);
                }
            }           
        }

        private void RegisterLogout(User User)
        {
            var Query = (from Login in ControlAccessUser.DataAccess.ControlAccessUserEntities.Instance.Logins
                         where Login.UserId == User.UserId && Login.DataTimeLogoutUser == null
                         select Login).ToList().Last();
            Query.DataTimeLogoutUser = DateTime.Now;
            ControlAccessUser.DataAccess.ControlAccessUserEntities.Instance.SaveChanges();
        }


        /// <summary>
        /// Verifica que se haga el registro de login si no existe un login previo sin el dato de logout
        /// </summary>
        [TestMethod]
        public void CorrectRegistratioOfNewLogin()
        {
            CheckLogin("gary", "123456");
            vPrincipalView.EnterDataLogoutSuccessful();
            pPrincipal.Logout();//Registrar Logout
            CheckLogin("gary", "123456");//Para registrar el login una segunda vez
            //Ahora verificamos que en la BD hayan almenos 2 logins registrados.            
            ICollection<Login> Login = (from Logins in ControlAccessUser.DataAccess.ControlAccessUserEntities.Instance.Logins
                                        where Logins.UserId == vPrincipalView.UserLogin.UserId
                                        select Logins).ToList();
            Assert.AreEqual(2, Login.Count);
        }

        /// <summary>
        /// Verifica que no se realice el registro de un nuevo login, porque existe un login sin dato de logout
        /// </summary>
        [TestMethod]
        public void NoRegistratioOfNewLogin()
        {
            CheckLogin("gary", "123456");
            CheckLogin("gary", "123456");//Para registrar el login una segunda vez
            //Ahora verificamos que en la BD haya solo 1 login registrado.            
            ICollection<Login> Login = (from Logins in ControlAccessUser.DataAccess.ControlAccessUserEntities.Instance.Logins
                                        where Logins.UserId == vPrincipalView.UserLogin.UserId
                                        select Logins).ToList();
            Assert.AreEqual(1, Login.Count);
        }
    }
}
